package com.lzx.applib.base;

import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.Nullable;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.VideoView;

import com.lzx.applib.R;
import com.lzx.applib.R2;
import com.lzx.applib.anim.ViewVisibleAnimation;
import com.lzx.applib.attacher.GestureAttacher;
import com.lzx.applib.listener.MediaListener;
import com.lzx.applib.utils.LogUtil;
import com.lzx.applib.utils.OddUtils;
import com.lzx.applib.utils.TimeUtil;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;


/**
 * Created by Administrator on 16/11/17.
 */

public class VideoFragment extends BaseFragment implements Handler.Callback {

    private static final String TAG = "VideoFragment";

    View fragmentContainer;

    @BindView(R2.id.video) VideoView videoView;
    @BindView(R2.id.video_cover) ImageView videoCover;
    @BindView(R2.id.video_play) ImageView videoPlay;
    @BindView(R2.id.video_loading) View videoLoading;

    @BindView(R2.id.video_lock) ImageView lockView;

    @BindView(R2.id.video_topbar) View topBar;
    @BindView(R2.id.video_go_back) View goBackView;
    @BindView(R2.id.video_share) View shareView;
    @BindView(R2.id.video_title) TextView videoTitle;


    @BindView(R2.id.video_control) View bottomBar;
    @BindView(R2.id.video_control_play) ImageView playControlView;
    @BindView(R2.id.video_control_scale) ImageView scaleView;
    @BindView(R2.id.video_control_bar) SeekBar seekBar;
    @BindView(R2.id.video_control_timer) TextView videoTimeView;

    @BindView(R2.id.video_figure) View figureView;
    @BindView(R2.id.video_figure_img) ImageView figureImg;
    @BindView(R2.id.video_figure_text) TextView figureText;

    Animation slideTopIn, slideTopOut, slideLeftIn, slideLeftOut, slideBottomIn, slideBottomOut, alphaIn, alphaOut;

    boolean controlViewShow = true;
    boolean lock = false;
    int currentAudio;
    protected String url;

    public static final int MSG_SHOW_CONTROL = 0x01;
    public static final int MSG_DISMISS_CONTROL = 0x02;
    public static final int MSG_SHOW_FIGURE_VIEW = 0x03;
    public static final int MSG_DISMISS_FIGURE_VIEW = 0x04;
    public static final int MSG_SEEK_VIDEO = 0x05;
    public static final int MSG_RESET_CURRENT_AUDIO = 0x06;
    SafeHandler handler;

    @Override
    public boolean handleMessage(Message msg) {
        switch (msg.what) {
            case MSG_SHOW_CONTROL:
                showControlView();
                break;
            case MSG_DISMISS_CONTROL:
                dismissControlView();
                break;
            case MSG_SHOW_FIGURE_VIEW:
                showFigureInfo(msg.arg1, msg.obj.toString());
                break;
            case MSG_DISMISS_FIGURE_VIEW:
                dismissFiguerView();
                break;
            case MSG_SEEK_VIDEO:
                seekTo(msg.arg1);
                break;
            case MSG_RESET_CURRENT_AUDIO:
                currentAudio = OddUtils.getCurrentAudio(getContext());
                break;
        }
        return true;
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        handler = new SafeHandler(getActivity(), this);
        currentAudio = OddUtils.getCurrentAudio(getContext());
        handler.sendEmptyMessageDelayed(MSG_DISMISS_CONTROL, 3000);
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        fragmentContainer = inflater.inflate(R.layout.fragment_video, container, false);
        ButterKnife.bind(this, fragmentContainer);
        initAnimation();
        initVideoView();
        initSeekBar();
        return fragmentContainer;
    }

    public void initAnimation() {
        slideTopIn = AnimationUtils.loadAnimation(getContext(), R.anim.slide_top_in);
        slideTopIn.setAnimationListener(new ViewVisibleAnimation(topBar, View.VISIBLE, View.VISIBLE));

        slideTopOut = AnimationUtils.loadAnimation(getContext(), R.anim.slide_top_out);
        slideTopOut.setAnimationListener(new ViewVisibleAnimation(topBar, View.VISIBLE, View.GONE));

        slideLeftIn = AnimationUtils.loadAnimation(getContext(), R.anim.slide_left_in);
        slideLeftIn.setAnimationListener(new ViewVisibleAnimation(lockView, View.VISIBLE, View.VISIBLE));

        slideLeftOut = AnimationUtils.loadAnimation(getContext(), R.anim.slide_left_out);
        slideLeftOut.setAnimationListener(new ViewVisibleAnimation(lockView, View.VISIBLE, View.GONE));

        slideBottomIn = AnimationUtils.loadAnimation(getContext(), R.anim.slide_bottom_in);
        slideBottomIn.setAnimationListener(new ViewVisibleAnimation(bottomBar, View.VISIBLE, View.VISIBLE));

        slideBottomOut = AnimationUtils.loadAnimation(getContext(), R.anim.slide_bottom_out);
        slideBottomOut.setAnimationListener(new ViewVisibleAnimation(bottomBar, View.VISIBLE, View.GONE));

        alphaIn = AnimationUtils.loadAnimation(getContext(), R.anim.alpha_in);
        alphaIn.setAnimationListener(new ViewVisibleAnimation(figureView, View.VISIBLE, View.VISIBLE));

        alphaOut = AnimationUtils.loadAnimation(getContext(), R.anim.alpha_out);
        alphaOut.setAnimationListener(new ViewVisibleAnimation(figureView, View.VISIBLE, View.GONE));
    }

    public void initVideoView() {
        GestureAttacher.attach(fragmentContainer, new GestureAttacher.SimpleGestureCallback() {

            @Override
            public void onSingleTap(MotionEvent event) {
                super.onSingleTap(event);
                if (controlViewShow) {
                    dismissControlView();
                } else {
                    showControlView();
                }
            }

            @Override
            public void onDoubleTap(MotionEvent event) {
                super.onDoubleTap(event);
                if (videoView.isPlaying()) {
                    videoView.pause();
                } else {
                    videoView.start();
                }
            }

            @Override
            public void onScrollHorizontal(float disCur, float disAll) {
                super.onScrollHorizontal(disCur, disAll);
                if (!lock) showVideoSeekInfo(disCur, disAll);
            }

            @Override
            public void onScrollVerticalLeft(float disCur, float disAll) {
                super.onScrollVerticalLeft(disCur, disAll);
                if (!lock) showVolumeInfo(disCur, disAll);
            }

            @Override
            public void onScrollVerticalRight(float disCur, float disAll) {
                super.onScrollVerticalRight(disCur, disAll);
                if (!lock) showLightInfo(disCur, disAll);
            }
        });
        videoView.setOnCompletionListener(mediaListenerAdapter);
        videoView.setOnErrorListener(mediaListenerAdapter);
        videoView.setOnPreparedListener(mediaListenerAdapter);
        videoView.setKeepScreenOn(true);
        videoView.setVideoURI(Uri.parse(url));
        videoView.start();
    }

    public void initSeekBar() {
        seekBar.setMax(100);
        seekBar.setEnabled(false);
        seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {

            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                float progress = seekBar.getProgress();
                int seekTo = (int) (progress * videoView.getDuration() / 100);
                seekTo(seekTo);
            }
        });
    }

    @OnClick(R2.id.video_control_scale) void changeScreenOrientation() {
        int orientation = getActivity().getRequestedOrientation();
        if (orientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
            getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        } else {
            getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        }
    }

    @OnClick(R2.id.video_lock) void changeLock() {
        lock = !lock;
        showControlView();
    }

    public void showControlView() {
        if (lock) {
            if (topBar.getVisibility() == View.VISIBLE) topBar.startAnimation(slideTopOut);
            if (bottomBar.getVisibility() == View.VISIBLE) bottomBar.startAnimation(slideBottomOut);
        } else {
            if (topBar.getVisibility() != View.VISIBLE) topBar.startAnimation(slideTopIn);
            if (bottomBar.getVisibility() != View.VISIBLE)bottomBar.startAnimation(slideBottomIn);
        }

        if (lockView.getVisibility() != View.VISIBLE)
            lockView.startAnimation(slideLeftIn);

        controlViewShow = true;

        handler.removeMessages(MSG_DISMISS_CONTROL);
        handler.sendEmptyMessageDelayed(MSG_DISMISS_CONTROL, 3000);
    }

    public void dismissControlView() {
        if (!lock) {
            topBar.startAnimation(slideTopOut);
            bottomBar.startAnimation(slideBottomOut);
        }
        lockView.startAnimation(slideLeftOut);
        controlViewShow = false;
    }

    public void showVideoSeekInfo(float disCur, float disAll) {
        int duration = videoView.getDuration();
        if (duration == -1) return;

        int width = videoView.getWidth();
        float progress = - disAll / width;
        int seekTime = (int) (duration * progress);
        int curTime = videoView.getCurrentPosition();

        final int seekTo = Math.max(0, Math.min(duration, seekTime + curTime));
        String figureInfo = getVideoTimeStr(seekTo);
        int imgRes = disAll < 0 ? android.R.drawable.ic_media_next : android.R.drawable.ic_media_previous;

        handler.removeMessages(MSG_SHOW_FIGURE_VIEW);
        handler.sendMessage(handler.obtainMessage(MSG_SHOW_FIGURE_VIEW, imgRes, 0, figureInfo));
        handler.removeMessages(MSG_SEEK_VIDEO);
        handler.sendMessageDelayed(handler.obtainMessage(MSG_SEEK_VIDEO, seekTo, 0), 500);
    }

    private void showLightInfo(float disCur, float disAll) {
        int height = videoView.getHeight();
        float progress = disCur / height;
        float curBrightness = OddUtils.getCurrentBrightness(getActivity());

        float toBrightness = Math.max(0, Math.min(1, progress + curBrightness));
        String light = (int) (toBrightness * 100) + "%";
        showFigureInfo(android.R.color.holo_red_light, light);
        OddUtils.setBrightness(getActivity(), toBrightness);
    }

    public void showVolumeInfo(float disCur, float disAll) {
        int height = videoView.getHeight();
        int allAudio = OddUtils.getMaxAudio(getActivity());
        float progress = disAll / height;
        float toAudio = Math.max(0, Math.min(allAudio, progress * allAudio + currentAudio));
        String volume = ((int) (toAudio * 100 / allAudio)) + "%";
        showFigureInfo(android.R.color.holo_green_light, volume);

        OddUtils.setAudio(getActivity(), (int) toAudio);

        handler.removeMessages(MSG_RESET_CURRENT_AUDIO);
        handler.sendEmptyMessageDelayed(MSG_RESET_CURRENT_AUDIO, 100);
    }

    private void showFigureInfo(int imgRes, String text) {
        figureText.setText(text);
        figureImg.setImageResource(imgRes);

        figureView.setVisibility(View.VISIBLE);
        handler.removeMessages(MSG_DISMISS_FIGURE_VIEW);
        handler.sendEmptyMessageDelayed(MSG_DISMISS_FIGURE_VIEW, 300);
    }

    public void dismissFiguerView() {
        figureView.startAnimation(alphaOut);
    }

    public void seekTo(int time) {
        LogUtil.d(TAG, "seekToSecond() called with: time = [" + time + "]");
        videoView.seekTo(time);
        mediaListenerAdapter.showVideoBuffering(true);
    }

    public void onScreenOrientationChange() {
        if (isLandscapeScreen()) {
            ((BaseActivity) getActivity()).fullScreen();
            fragmentContainer.setFocusable(true);
            fragmentContainer.setFocusableInTouchMode(true);
            fragmentContainer.requestFocus();
            fragmentContainer.setOnKeyListener(new View.OnKeyListener() {
                @Override
                public boolean onKey(View v, int keyCode, KeyEvent event) {
                    if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
                        changeScreenOrientation();
                        return true;
                    }
                    return false;
                }
            });
        } else {
            fragmentContainer.setOnKeyListener(null);
            ((BaseActivity) getActivity()).noFullScreen();
        }
        fragmentContainer.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                fragmentContainer.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                ViewGroup.LayoutParams lp = fragmentContainer.getLayoutParams();
                if (isLandscapeScreen()) {
                    lp.width = Math.max(BaseApplication.mScreenHeight, BaseApplication.mScreenWidth);
                } else {
                    lp.width = Math.min(BaseApplication.mScreenHeight, BaseApplication.mScreenWidth);
                }
                lp.height = lp.width * 9 / 16;
                LogUtil.d(TAG, "onGlobalLayout:", lp.width, lp.height);
                fragmentContainer.setLayoutParams(lp);
            }
        });
        showControlView();
    }

    private String getVideoTimeStr(int videoPosition) {
        String positionStr = TimeUtil.getVideoTimeByMilliSecond(videoPosition);
        String all = TimeUtil.getVideoTimeByMilliSecond(videoView.getDuration());
        String videoTimeInfo = positionStr + "/" + all;
        return videoTimeInfo;
    }

    public MediaListener.MediaListenerAdapter mediaListenerAdapter = new MediaListener.MediaListenerAdapter() {
        @Override
        public void onPrepared(MediaPlayer mp) {
            super.onPrepared(mp);
            seekBar.setEnabled(true);
        }

        @Override
        public boolean onError(MediaPlayer mp, int what, int extra) {
            return super.onError(mp, what, extra);
        }

        @Override
        public void onCompletion(MediaPlayer mp) {
            super.onCompletion(mp);
        }

        @Override
        public void showVideoBuffering(boolean buffering) {
            videoLoading.setVisibility(buffering ? View.VISIBLE : View.GONE);
        }

        @Override
        public boolean onInfo(MediaPlayer mp, int what, int extra) {
            super.onInfo(mp, what, extra);
            seekBar.setProgress((int) (videoView.getCurrentPosition()*100f/videoView.getDuration()));
            videoTimeView.setText(getVideoTimeStr(videoView.getCurrentPosition()));
            return false;
        }

        @Override
        public void onBufferingUpdate(MediaPlayer mp, int percent) {
            super.onBufferingUpdate(mp, percent);
            seekBar.setSecondaryProgress(percent);
        }
    };

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE
                || newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
            onScreenOrientationChange();
        }
    }

    private boolean isLandscapeScreen() {
        final int orientation = getActivity().getRequestedOrientation();
        if (orientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
            return true;
        } else {
            return false;
        }
    }

    @Override
    public boolean onBackPressed() {
        if (isLandscapeScreen()) {
            changeScreenOrientation();
            return true;
        }
        return false;
    }
}
